﻿using System;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.Security;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using System.Web;
using System.Text.RegularExpressions;
using System.Xml.Linq;
using System.Collections.Generic;
using System.Linq;
using System.Configuration;

namespace FBAUserManagement.UserManagement
{
    public partial class UserManagementUserControl : UserControl
    {
        private String userNamePrefix = ConfigurationManager.AppSettings["FBAUserNamePrefix"];

        protected void Page_Load(object sender, EventArgs e)
        {
            if (String.IsNullOrEmpty(userNamePrefix)) {
                statusMsg.Text = "FBA User Name Prefix not found!";
                statusMsg.ForeColor = System.Drawing.Color.Red;
                MultiView.Visible = false;
                TopMenu.Visible = false;
                return;
            }
            if (!Page.IsPostBack)
            {
                var viewIndex = MultiView.ActiveViewIndex;
                LoadView(viewIndex);
            }
        }

        protected void TopMenu_MenuItemClick(object sender, MenuEventArgs e)
        {
            var viewIndex = int.Parse(e.Item.Value);
            MultiView.ActiveViewIndex = viewIndex;
            LoadView(viewIndex);
        }

        private void LoadView(int viewIndex)
        {
            switch (viewIndex)
            {
                case 0:
                    LoadCreateView();
                    break;
                case 1:
                    LoadEditView();
                    break;
            };
            statusMsg.Text = String.Empty;
        }

        private Dictionary<String, String> GetSPGroups()
        {
            try
            {
                SPWeb spWeb = SPControl.GetContextWeb(HttpContext.Current);

                XDocument xdoc = XDocument.Parse(spWeb.SiteGroups.Xml);
                var spGroupCollection = xdoc.Descendants("Group").ToDictionary(o => o.Attribute("Name").Value, o => o.Attribute("ID").Value);

                return spGroupCollection;
            }
            catch (Exception ex)
            {
                throw ex;
            }
        }

        #region Create View

        private void LoadCreateView()
        {
            LoadGroupDDL(cblGroup);
        }

        protected void btnSave_Click(object sender, EventArgs e)
        {

            var userName = txtUserName.Text.Trim();
            var password = txtPassword.Text.Trim();
            var rePassword = txtRePassword.Text.Trim();
            var email = txtEmail.Text.Trim();
            var groupList = new List<String>();

            if (String.IsNullOrEmpty(userName) || String.IsNullOrEmpty(password))
            {
                statusMsg.Text = "Empty valuse are not allowed in any field!";
                statusMsg.ForeColor = System.Drawing.Color.Red;
                return;
            }

            if (!password.Equals(rePassword))
            {
                statusMsg.Text = "Password does not match!";
                statusMsg.ForeColor = System.Drawing.Color.Red;
                return;
            }

            if (!isEmail(email)) {
                statusMsg.Text = "Wrong Email address!";
                statusMsg.ForeColor = System.Drawing.Color.Red;
                return;
            }

            groupList = cblGroup.Items.Cast<ListItem>().Where(i => i.Selected).Select(o=>o.Text).ToList();

            if (groupList.Count < 1)
            {
                statusMsg.Text = "Select a Group!";
                statusMsg.ForeColor = System.Drawing.Color.Red;
                return;
            }
            try
            {
                MembershipUser membershipUser = Membership.CreateUser(userName, password,email);

                SPWeb spWeb = SPContext.Current.Web;
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    spWeb.AllowUnsafeUpdates = true;

                    SPUser spUser = spWeb.EnsureUser(userNamePrefix + userName);
                    foreach (string groupName in groupList)
                    {
                        SPGroup spGroup = spWeb.SiteGroups[groupName];
                        spGroup.AddUser(spUser);
                    }
                    spWeb.AllowUnsafeUpdates = false;
                });

                statusMsg.Text = "User Created Succesfully.";
                statusMsg.ForeColor = System.Drawing.Color.Green;
                return;
            }
            catch (Exception ex)
            {
                statusMsg.Text = ex.Message;
                statusMsg.ForeColor = System.Drawing.Color.Red;
                return;
            }
        }

        private void LoadGroupDDL(CheckBoxList cblGroup)
        {
            try
            {
                Dictionary<string, string> spGroupCollection = GetSPGroups();
                cblGroup.DataSource = spGroupCollection;
                cblGroup.DataTextField = "Key";
                cblGroup.DataValueField = "Value";
                cblGroup.DataBind();
            }
            catch (Exception ex)
            {
                statusMsg.Text = ex.Message;
                statusMsg.ForeColor = System.Drawing.Color.Red;
                return;
            }
        }

        #endregion

        #region Edit View

        private void LoadEditView()
        {
            SPWeb spWeb = SPContext.Current.Web;
            SPUserCollection spUserCollection = spWeb.AllUsers;
            ddlUserList.Items.Clear();
            foreach (SPUser spUser in spUserCollection)
            {
                if (spUser.LoginName.Contains(userNamePrefix.ToLower()))
                {
                    ddlUserList.Items.Add(new ListItem(spUser.LoginName.Replace(userNamePrefix.ToLower(), "")));
                }
            }

            LoadGroupDDL(cblGroupEdit);
            if (ddlUserList.SelectedItem!=null)
            LoadUser(ddlUserList.SelectedItem.Text);
        }

        private void LoadUser(String userName)
        {

            foreach (ListItem li in cblGroupEdit.Items)
            {
                li.Selected = false;
            } 

            SPWeb spWeb = SPContext.Current.Web;
            SPSecurity.RunWithElevatedPrivileges(delegate
            {
                SPUser spUser = spWeb.EnsureUser(userNamePrefix + userName);
                lblUserName.Text = spUser.LoginName.Replace(userNamePrefix.ToLower(), "");

                var groupArray=spUser.Groups.Cast<SPGroup>().Select(o=>o.Name).ToArray();

                foreach (ListItem li in cblGroupEdit.Items)
                {
                    if (groupArray.Contains(li.Text))
                        li.Selected = true;
                }

                txtEmailEdit.Text = spUser.Email;
            });
            statusMsg.Text = String.Empty;
        }

        protected void ddlUserListChanged(object sender, EventArgs e)
        {
            LoadUser(ddlUserList.SelectedItem.Text);
        }

        private bool RemoveUser(String user)
        {
            bool status = false;
            try
            {
                var spUser = userNamePrefix + user.Trim();
                SPWeb spWeb = SPContext.Current.Web;
                SPUserCollection spUserCollection = spWeb.AllUsers;
                spUserCollection.Remove(spUser);

                status = Membership.DeleteUser(user, true);
            }
            catch (Exception ex)
            {
                throw ex;
            }

            return status;
        }

        protected void btnDelete_Click(object sender, EventArgs e)
        {
            try
            {
                bool status = RemoveUser(lblUserName.Text);
                if (status)
                {
                    statusMsg.Text = "Successfully deleted user " + lblUserName.Text;
                    statusMsg.ForeColor = System.Drawing.Color.Green;
                    LoadEditView();
                }
                else
                {
                    statusMsg.Text = "Error deleting user " + lblUserName.Text;
                    statusMsg.ForeColor = System.Drawing.Color.Red;
                }
            }
            catch (Exception ex)
            {
                statusMsg.Text = ex.Message;
            }

        }

        protected void btnSaveUser_Click(object sender, EventArgs e)
        {
            try
            {
                bool status = UpdateUser(lblUserName.Text);
                if (status)
                {
                    statusMsg.Text = "Successfully Updated user " + lblUserName.Text;
                    statusMsg.ForeColor = System.Drawing.Color.Green;
                }
                else
                {
                    statusMsg.Text = "Error updating user " + lblUserName.Text;
                    statusMsg.ForeColor = System.Drawing.Color.Red;
                }
            }
            catch (Exception ex)
            {
                statusMsg.Text = ex.Message;
            }
        }

        private bool UpdateUser(string userName)
        {
            bool status = false;
            var groupArray = cblGroupEdit.Items.Cast<ListItem>().Where(i => i.Selected).Select(o => o.Text).ToArray();
            var email = txtEmailEdit.Text.Trim();
            try
            {
                SPWeb spWeb = SPContext.Current.Web;
                SPSecurity.RunWithElevatedPrivileges(delegate
                {
                    spWeb.AllowUnsafeUpdates = true;

                    SPUser spUser = spWeb.EnsureUser(userNamePrefix + userName);
                    foreach (SPGroup spGroup in spWeb.Groups)
                    {
                        if (groupArray.Contains(spGroup.Name))
                            spGroup.AddUser(spUser);
                        else
                            spGroup.RemoveUser(spUser);
                    }

                    if (isEmail(email))
                    {
                        spUser.Email = email;
                        spUser.Update();
                        status = true;
                    }
                    else
                        status = false;

                    spWeb.AllowUnsafeUpdates = false;
                });
            }
            catch (Exception ex) {
                status = false;
            }
            return status;
        }

        #endregion


        #region Utils
        public static bool isEmail(string inputEmail)
        {
            string strRegex = @"^([a-zA-Z0-9_\-\.]+)@((\[[0-9]{1,3}" +
                  @"\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([a-zA-Z0-9\-]+\" +
                  @".)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$";
            Regex re = new Regex(strRegex);
            if (re.IsMatch(inputEmail))
                return (true);
            else
                return (false);
        }
        #endregion 
    }
}
